package main

import (
	"fmt"
	"math"
)

// 简单函数 - 无参数无返回值
func sayHello() {
	fmt.Println("Hello, Go!")
}

// 带参数的函数
func greet(name string) {
	fmt.Printf("你好, %s!\n", name)
}

// 带多个参数的函数
func introduce(name string, age int) {
	fmt.Printf("我是 %s, 今年 %d 岁\n", name, age)
}

// 带返回值的函数
func add(a, b int) int {
	return a + b
}

// 带多个返回值的函数
func divide(a, b float64) (float64, error) {
	if b == 0 {
		return 0, fmt.Errorf("除数不能为零")
	}
	return a / b, nil
}

// 命名返回值
func rectangleStats(length, width float64) (area, perimeter float64) {
	area = length * width
	perimeter = 2 * (length + width)
	return // 简短返回形式
}

// 可变参数函数
func sum(nums ...int) int {
	total := 0
	for _, num := range nums {
		total += num
	}
	return total
}

// 递归函数
func factorial(n int) int {
	if n <= 1 {
		return 1
	}
	return n * factorial(n-1)
}

// 函数作为参数
func apply(op func(int, int) int, a, b int) int {
	return op(a, b)
}

// 函数作为返回值
func getOperation(op string) func(int, int) int {
	switch op {
	case "add":
		return func(a, b int) int {
			return a + b
		}
	case "multiply":
		return func(a, b int) int {
			return a * b
		}
	default:
		return func(a, b int) int {
			return 0
		}
	}
}

func main() {
	fmt.Println("7. 函数")

	// 调用简单函数
	sayHello()

	// 调用带参数的函数
	greet("张三")

	// 调用带多个参数的函数
	introduce("李四", 25)

	// 调用带返回值的函数
	result := add(10, 20)
	fmt.Printf("10 + 20 = %d\n", result)

	// 调用带多个返回值的函数
	if quotient, err := divide(10, 3); err != nil {
		fmt.Printf("错误: %v\n", err)
	} else {
		fmt.Printf("10 / 3 = %.2f\n", quotient)
	}

	// 调用带命名返回值的函数
	area, perimeter := rectangleStats(5, 3)
	fmt.Printf("矩形面积: %.2f, 周长: %.2f\n", area, perimeter)

	// 调用可变参数函数
	fmt.Printf("sum(): %d\n", sum())
	fmt.Printf("sum(1, 2): %d\n", sum(1, 2))
	fmt.Printf("sum(1, 2, 3, 4, 5): %d\n", sum(1, 2, 3, 4, 5))

	// 调用递归函数
	fmt.Printf("5! = %d\n", factorial(5))

	// 函数作为参数
	addResult := apply(func(a, b int) int {
		return a + b
	}, 10, 20)
	fmt.Printf("apply(add, 10, 20) = %d\n", addResult)

	multiplyResult := apply(func(a, b int) int {
		return a * b
	}, 10, 20)
	fmt.Printf("apply(multiply, 10, 20) = %d\n", multiplyResult)

	// 函数作为返回值
	addFunc := getOperation("add")
	multiplyFunc := getOperation("multiply")
	fmt.Printf("addFunc(5, 3) = %d\n", addFunc(5, 3))
	fmt.Printf("multiplyFunc(5, 3) = %d\n", multiplyFunc(5, 3))

	// 匿名函数
	square := func(x int) int {
		return x * x
	}
	fmt.Printf("square(5) = %d\n", square(5))

	// 立即执行函数表达式
	result2 := func(x, y int) int {
		return int(math.Pow(float64(x), float64(y)))
	}(2, 3)
	fmt.Printf("2^3 = %d\n", result2)
}
